package com.ruoyi.huanjing.controller;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.huanjing.entity.AtmosphericLogData;
import com.ruoyi.huanjing.entity.dto.*;
import com.ruoyi.huanjing.service.IAtmosphericNcFileService;
import com.ruoyi.huanjing.tool.ElectromagneticDataTool;
import com.ruoyi.huanjing.tool.ModisDataParser;
import com.ruoyi.huanjing.tool.OceanParamBinaryParser;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ucar.ma2.InvalidRangeException;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;

/**
 * 大气环境NC文件控制器
 *
 * @author xu
 * @date 2025-07-23
 */
@RestController
@RequestMapping("/atmospheric")
public class AtmosphericNcFileController extends BaseController {
    @Autowired
    private IAtmosphericNcFileService atmosphericNcFileService;


    @Anonymous
    @ApiOperation(value = "判断文件类型", notes = "判断文件类型")
    @PostMapping("/dimension")
    public AjaxResult dimension(@RequestBody Map<String, Object> requestBody) throws IOException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        return success(atmosphericNcFileService.dimension(filePath));
    }

    @Anonymous
    @ApiOperation(value = "读取区域列表", notes = "读取区域列表")
    @GetMapping("/regionList")
    public AjaxResult readRegionList(String filePath) {
        return success(atmosphericNcFileService.readRegionList(filePath));
    }


    @Anonymous
    @ApiOperation(value = "读取太阳类型有效时间", notes = "读取太阳类型有效时间")
    @PostMapping("/opticalProperties/sun/readValidTime")
    public AjaxResult readSunValidTime(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(processReadValidTime(requestBody)) ;
    }

    private AjaxResult processReadValidTime(Map<String, Object> requestBody) throws IOException {
        // 校验filePath非空（必填参数）
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();

        // 处理year参数（可为空，不强制校验）
        Integer year = null;
        Object yearObj = requestBody.get("year");
        if (yearObj != null) {
            try {
                year = Integer.parseInt(yearObj.toString());
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("year参数格式错误，必须为整数", e);
            }
        }

        // 处理month参数（可为空，不强制校验）
        Integer month = null;
        Object monthObj = requestBody.get("month");
        if (monthObj != null) {
            try {
                month = Integer.parseInt(monthObj.toString());
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("month参数格式错误，必须为整数", e);
            }
        }

        // 调用服务层方法，传入可能为null的year和month
        return success(atmosphericNcFileService.sunReadValidTime(filePath, year, month));
    }

    @Anonymous
    @ApiOperation(value = "读取太阳类型所有参数", notes = "读取太阳类型所有参数")
    @PostMapping("/opticalProperties/sun/readSunVariables")
    public AjaxResult readSunVariables(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(processReadAllVariables(requestBody));
    }

    // 共享处理逻辑
    private AjaxResult processReadAllVariables(Map<String, Object> requestBody) {
        // 参数校验
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();

        // 调用服务层方法
        return success(atmosphericNcFileService.sunReadAllVariables(filePath));
    }


    @Anonymous
    @ApiOperation(value = "读取太阳类型热力图", notes = "根据经纬度和变量名读取太阳类型热力图")
    @PostMapping("/opticalProperties/sun/readSunHeatmap")
    public AjaxResult readSunHeatmap(@RequestBody Map<String, Object> requestBody) throws IOException, InvalidRangeException {
            return success(processReadSunHeatmap(requestBody));
    }

    // 热力图数据共享逻辑
    private AjaxResult processReadSunHeatmap(Map<String, Object> requestBody) throws IOException, InvalidRangeException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();

        return success(atmosphericNcFileService.sunReadHeatmap(filePath, timeIndex, val));
    }

    @Anonymous
    @ApiOperation(value = "读取太阳类型热力图部分", notes = "根据经纬度和变量名读取太阳类型热力图部分")
    @PostMapping("/opticalProperties/sun/readSunHeatmapRegion")
    public AjaxResult readSunHeatmapRegion(@RequestBody Map<String, Object> requestBody) throws IOException, InvalidRangeException {
        return success(processReadSunHeatmapRegion(requestBody));
    }


    // 热力图数据共享逻辑
    private AjaxResult processReadSunHeatmapRegion(Map<String, Object> requestBody) throws IOException, InvalidRangeException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "路径不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "时间不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "参数不能为空").toString();
        Long regionId = Long.parseLong(Objects.requireNonNull(requestBody.get("regionId"), "区域不能为空").toString());
        Double precision = Double.parseDouble(Objects.requireNonNull(requestBody.get("precision"), "precision不能为空").toString());
        return success(atmosphericNcFileService.processReadSunHeatmapRegion(filePath, timeIndex, val,regionId,precision));
    }
    @Anonymous
    @ApiOperation(value = "读取太阳类型折线图", notes = "根据经纬度和变量名读取太阳类型时间序列数据")
    @PostMapping("/opticalProperties/sun/readSunLineChart")
    public AjaxResult readSunLineChart(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(sunReadLineChart(requestBody));
    }


    // 折线图数据共享逻辑
    private AjaxResult sunReadLineChart(Map<String, Object> requestBody) throws IOException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        double targetLon = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLon"), "targetLon不能为空").toString());
        double targetLat = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLat"), "targetLat不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        List<Integer> timeIndexList = (List<Integer>) requestBody.get("timeIndexList");

        return success(atmosphericNcFileService.sunReadLineChart(filePath, targetLon, targetLat, val, timeIndexList));
    }



    @Anonymous
    @ApiOperation(value = "读取大气廓线类型有效时间", notes = "读取大气廓线类型有效时间")
    @PostMapping("/opticalProperties/profiles/readProfilesValidTime")
    public AjaxResult readProfilesValidTime(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(processReadValidTime(requestBody));
        }




    @Anonymous
    @ApiOperation(value = "读取大气廓线类型所有参数", notes = "读取大气廓线类型所有参数")
    @PostMapping("/opticalProperties/profiles/readProfilesVariables")
    public AjaxResult readProfilesVariables(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(processReadAllVariables(requestBody));
    }

    @Anonymous
    @ApiOperation(value = "读取大气廓线类型压力值", notes = "读取大气廓线类型所有参数")
    @PostMapping("/opticalProperties/profiles/readProfilesPressureLevel")
    public AjaxResult readProfilesPressureLevel(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(processReadAllPressureLevel(requestBody));
    }


    private AjaxResult processReadAllPressureLevel(Map<String, Object> requestBody) throws IOException {
        // 校验filePath非空（必填参数）
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();
        return success(atmosphericNcFileService.processReadAllPressureLevel(filePath));
    }


    @Anonymous
    @ApiOperation(value = "读取大气廓线类型热力图", notes = "根据经纬度和变量名读取大气廓线类型热力图")
    @PostMapping("/opticalProperties/profiles/readProfilesHeatmap")
    public AjaxResult readProfilesHeatmap(@RequestBody Map<String, Object> requestBody) throws IOException, InvalidRangeException {

            return success(processReadProfilesHeatmap(requestBody));
    }


    // 热力图数据共享逻辑
    private AjaxResult processReadProfilesHeatmap(Map<String, Object> requestBody) throws IOException, InvalidRangeException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        int pressureIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("pressureIndex"), "pressureIndex不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        return success(atmosphericNcFileService.profilesReadHeatmap(filePath, timeIndex, pressureIndex, val));
    }


    @Anonymous
    @ApiOperation(value = "读取大气廓线类型热力图部分", notes = "根据经纬度和变量名读取大气廓线类型热力图部分")
    @PostMapping("/opticalProperties/profiles/readProfilesHeatmapByRegion")
    public AjaxResult readProfilesHeatmapByRegion(@RequestBody Map<String, Object> requestBody) throws IOException, InvalidRangeException {

            return success(processReadProfilesHeatmapByRegion(requestBody));
    }
    // 部分热力图数据共享逻辑
    private AjaxResult processReadProfilesHeatmapByRegion(Map<String, Object> requestBody) throws IOException, InvalidRangeException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        int pressureIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("pressureIndex"), "pressureIndex不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        Long regionId = Long.valueOf(Objects.requireNonNull(requestBody.get("regionId"), "region不能为空").toString());
        Double precision = Double.valueOf(Objects.requireNonNull(requestBody.get("precision"), "precision不能为空").toString());
        return success(atmosphericNcFileService.processReadProfilesHeatmapByRegion(filePath, timeIndex, pressureIndex, val, regionId, precision));
    }
    @Anonymous
    @ApiOperation(value = "读取大气廓线类型折线图", notes = "根据经纬度和变量名读取大气廓线类型时间序列数据")
    @PostMapping("/opticalProperties/sun/readProfilesLineChart")
    public AjaxResult readProfilesLineChart(@RequestBody Map<String, Object> requestBody) throws IOException {
            return success(profilesReadLineChart(requestBody));
    }

    // 折线图数据共享逻辑
    private AjaxResult profilesReadLineChart(Map<String, Object> requestBody) throws IOException {
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        double targetLon = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLon"), "targetLon不能为空").toString());
        double targetLat = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLat"), "targetLat不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        return success(atmosphericNcFileService.profilesReadLineChart(filePath, targetLon, targetLat, val,timeIndex));
    }









    // 定义 X 轴描述映射，key 是 VisualizeType，value 是包含中文名和单位的 Map
    private static final Map<ElectromagneticDataTool.VisualizeType, Map<String, String>> E_X_AXIS_DESC_MAP = new EnumMap<>(ElectromagneticDataTool.VisualizeType.class);
    // 定义 Y 轴描述映射，key 是 VisualizeType，value 是包含中文名和单位的 Map
    private static final Map<ElectromagneticDataTool.VisualizeType, Map<String, String>> E_Y_AXIS_DESC_MAP = new EnumMap<>(ElectromagneticDataTool.VisualizeType.class);

    static {
        // 初始化平均散射系数的描述
        Map<String, String> avgScatterXMap = new HashMap<>();
        avgScatterXMap.put("name", "擦地角");
        avgScatterXMap.put("unit", "(°)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.AVERAGE_SCATTERING, avgScatterXMap);

        Map<String, String> avgScatterYMap = new HashMap<>();
        avgScatterYMap.put("name", "平均散射系数");
        avgScatterYMap.put("unit", "(dB)");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.AVERAGE_SCATTERING, avgScatterYMap);

        // 初始化时变散射系数的描述
        Map<String, String> timeVaryScatterXMap = new HashMap<>();
        timeVaryScatterXMap.put("name", "时间");
        timeVaryScatterXMap.put("unit", "(s)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_VARYING_SCATTERING, timeVaryScatterXMap);

        Map<String, String> timeVaryScatterYMap = new HashMap<>();
        timeVaryScatterYMap.put("name", "时变散射系数");
        timeVaryScatterYMap.put("unit", "(dB)");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_VARYING_SCATTERING, timeVaryScatterYMap);

        // 初始化幅度概率密度的描述
        Map<String, String> ampPdfXMap = new HashMap<>();
        ampPdfXMap.put("name", "归一化幅值");
        ampPdfXMap.put("unit", "(X/<X>)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.AMPLITUDE_PDF, ampPdfXMap);

        Map<String, String> ampPdfYMap = new HashMap<>();
        ampPdfYMap.put("name", "幅度概率密度");
        ampPdfYMap.put("unit", "(PDF)");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.AMPLITUDE_PDF, ampPdfYMap);

        // 初始化时间相关特性的描述
        Map<String, String> timeCorrXMap = new HashMap<>();
        timeCorrXMap.put("name", "时间差");
        timeCorrXMap.put("unit", "(ms)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_CORRELATION, timeCorrXMap);

        Map<String, String> timeCorrYMap = new HashMap<>();
        timeCorrYMap.put("name", "时间相关系数");
        timeCorrYMap.put("unit", "");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_CORRELATION, timeCorrYMap);

        // 初始化距离相关特性的描述
        Map<String, String> distCorrXMap = new HashMap<>();
        distCorrXMap.put("name", "距离");
        distCorrXMap.put("unit", "(m)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DISTANCE_CORRELATION, distCorrXMap);

        Map<String, String> distCorrYMap = new HashMap<>();
        distCorrYMap.put("name", "距离相关系数");
        distCorrYMap.put("unit", "");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DISTANCE_CORRELATION, distCorrYMap);

        // 初始化多普勒谱的描述
        Map<String, String> dopplerSpectrumXMap = new HashMap<>();
        dopplerSpectrumXMap.put("name", "多普勒频率");
        dopplerSpectrumXMap.put("unit", "(Hz)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DOPPLER_SPECTRUM, dopplerSpectrumXMap);

        Map<String, String> dopplerSpectrumYMap = new HashMap<>();
        dopplerSpectrumYMap.put("name", "多普勒谱密度");
        dopplerSpectrumYMap.put("unit", "(dBmW/Hz)");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DOPPLER_SPECTRUM, dopplerSpectrumYMap);

        // 初始化一维图像的描述
        Map<String, String> image1DXMap = new HashMap<>();
        image1DXMap.put("name", "距离");
        image1DXMap.put("unit", "(m)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.IMAGE_1D, image1DXMap);

        Map<String, String> image1DYMap = new HashMap<>();
        image1DYMap.put("name", "回波幅值");
        image1DYMap.put("unit", "(dB)");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.IMAGE_1D, image1DYMap);

        // 初始化距离 - 脉冲的描述
        Map<String, String> distPulseXMap = new HashMap<>();
        distPulseXMap.put("name", "距离门");
        distPulseXMap.put("unit", "(m)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DISTANCE_PULSE, distPulseXMap);

        Map<String, String> distPulseYMap = new HashMap<>();
        distPulseYMap.put("name", "信号强度（实部）");
        distPulseYMap.put("unit", "");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.DISTANCE_PULSE, distPulseYMap);

        // 初始化时变多普勒谱的描述
        Map<String, String> timeDopplerXMap = new HashMap<>();
        timeDopplerXMap.put("name", "多普勒频率");
        timeDopplerXMap.put("unit", "(Hz)");
        E_X_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_DOPPLER, timeDopplerXMap);

        Map<String, String> timeDopplerYMap = new HashMap<>();
        timeDopplerYMap.put("name", "谱密度");
        timeDopplerYMap.put("unit", "");
        E_Y_AXIS_DESC_MAP.put(ElectromagneticDataTool.VisualizeType.TIME_DOPPLER, timeDopplerYMap);
    }


    /**
     * 读取并解析海洋电磁特性数据文件，支持按类型提取特定数据块并可视化
     *
     * @param requestBody 请求参数Map，必须包含以下键值对：
     *   - filePath (String): 待解析的二进制数据文件路径（必填）
     *   - type (String): 数据类型，取值范围为以下枚举值的字符串形式：
     *     - AVERAGE_SCATTERING: 平均散射系数
     *     - TIME_VARYING_SCATTERING: 时变散射系数
     *     - AMPLITUDE_PDF: 幅度概率密度
     *     - TIME_CORRELATION: 时间相关特性
     *     - DISTANCE_CORRELATION: 距离相关特性
     *     - DOPPLER_SPECTRUM: 多普勒谱
     *     - IMAGE_1D: 一维图像
     *     - DISTANCE_PULSE: 距离-脉冲数据
     *     - TIME_DOPPLER: 时变多普勒谱
     *
     * @return 成功时返回包含解析结果的AjaxResult，失败时返回错误信息
     *         解析结果格式根据type参数不同而异，具体如下：
     *         - 基础数据类型（前7种）：返回DataBlock对象，包含长度和二维数据点
     *         - DISTANCE_PULSE: 返回DistancePulseData对象，包含距离门、脉冲数及复数数据
     *         - TIME_DOPPLER: 返回TimeDopplerSpectrum对象，包含多普勒频率、时间点及谱密度
     */
    @Anonymous
    @ApiOperation(value = "读取海洋电磁特性数据（支持指定序号)", notes = "读取海洋电磁特性数据（支持指定序号）")
    @PostMapping("/readMarineElectromagneticData")
    public AjaxResult readMarineElectromagneticData(@RequestBody Map<String, Object> requestBody) {
        // 1. 获取参数
        String filePath = Objects.requireNonNull(requestBody.get("filePath"), "filePath不能为空").toString();
        String typeStr = Objects.requireNonNull(requestBody.get("type"), "type不能为空").toString();
        Integer index = (requestBody.get("index") instanceof Number)
                ? ((Number) requestBody.get("index")).intValue()
                : null; // 序号参数（可为null，默认返回第一条）

        // 2. 转换数据类型
        ElectromagneticDataTool.VisualizeType type;
        try {
            type = ElectromagneticDataTool.VisualizeType.valueOf(typeStr.toUpperCase());
        } catch (IllegalArgumentException e) {
            return error("无效的type参数，可选值: " + Arrays.toString(ElectromagneticDataTool.VisualizeType.values()));
        }

        // 3. 解析数据并提取结果
        ElectromagneticDataTool tool = new ElectromagneticDataTool(filePath);
        try {
            tool.parse(false, type); // 仅解析，不生成后端图表
            Map<String, Object> result = new HashMap<>();

            if (isBasicType(type)) {
                // 基础数据（单条曲线，无需序号）
                BasicDataDTO basicDTO = tool.getBasicDataDTO(type);
                result.put("xAxis", basicDTO.getXAxis());
                result.put("yAxis", basicDTO.getYAxis());
                result.put("totalCount", 1); // 固定1条
                result.put("currentIndex", 1);
            } else if (type == ElectromagneticDataTool.VisualizeType.DISTANCE_PULSE) {
                // 距离-脉冲数据（多条曲线，支持序号）
                MultiCurveDataDTO dto = tool.getDistancePulseByIndex(index);
                result.put("xAxis", dto.getXAxis());
                result.put("yAxis", dto.getYAxis());
                result.put("totalCount", dto.getTotalCount());
                result.put("currentIndex", dto.getCurrentIndex());
            } else if (type == ElectromagneticDataTool.VisualizeType.TIME_DOPPLER) {
                // 时变多普勒谱（多条曲线，支持序号）
                MultiCurveDataDTO dto = tool.getTimeDopplerByIndex(index);
                result.put("xAxis", dto.getXAxis());
                result.put("yAxis", dto.getYAxis());
                result.put("totalCount", dto.getTotalCount());
                result.put("currentIndex", dto.getCurrentIndex());
            }

            // 补充 X、Y 轴描述信息
            Map<String, String> xDesc = E_X_AXIS_DESC_MAP.get(type);
            Map<String, String> yDesc = E_Y_AXIS_DESC_MAP.get(type);
            result.put("xAxisDesc", xDesc);
            result.put("yAxisDesc", yDesc);

            return success(result);
        } catch (Exception e) {
            return error("读取失败: " + e.getMessage());
        }
    }

    // 判断是否为基础单曲线类型
    private boolean isBasicType(ElectromagneticDataTool.VisualizeType type) {
        return type == ElectromagneticDataTool.VisualizeType.AVERAGE_SCATTERING ||
                type == ElectromagneticDataTool.VisualizeType.TIME_VARYING_SCATTERING ||
                type == ElectromagneticDataTool.VisualizeType.AMPLITUDE_PDF ||
                type == ElectromagneticDataTool.VisualizeType.TIME_CORRELATION ||
                type == ElectromagneticDataTool.VisualizeType.DISTANCE_CORRELATION ||
                type == ElectromagneticDataTool.VisualizeType.DOPPLER_SPECTRUM ||
                type == ElectromagneticDataTool.VisualizeType.IMAGE_1D;
    }



    // 1. 基本特性参数的描述（包含中文名和单位）
    private static final Map<String, Map<String, String>> BASIC_PARAMS_DESC = new HashMap<String, Map<String, String>>() {{
        // 直接初始化每个参数的描述（key:参数英文名，value:包含中文名和单位的Map）
        put("significantWaveHeight", new HashMap<String, String>() {{
            put("name", "有效波高");
            put("unit", "m");
        }});
        put("maxWaveHeight", new HashMap<String, String>() {{
            put("name", "最大波高");
            put("unit", "m");
        }});
        put("avgWaveHeight", new HashMap<String, String>() {{
            put("name", "平均波高");
            put("unit", "m");
        }});
        put("waveDirection", new HashMap<String, String>() {{
            put("name", "波向");
            put("unit", "°");
        }});
        put("wavePeriod", new HashMap<String, String>() {{
            put("name", "波周期");
            put("unit", "s");
        }});
        put("currentSpeed", new HashMap<String, String>() {{
            put("name", "流速");
            put("unit", "m/s");
        }});
        put("currentDirection", new HashMap<String, String>() {{
            put("name", "流向");
            put("unit", "°");
        }});
        put("seaSurfaceTemp", new HashMap<String, String>() {{
            put("name", "海表温度");
            put("unit", "℃");
        }});
        put("seaStateLevel", new HashMap<String, String>() {{
            put("name", "海情等级");
            put("unit", "");
        }});
    }};

    // 2. X轴描述（key：可视化类型，value：包含中文名和单位的Map）
    private static final Map<OceanParamBinaryParser.VisualizeType, Map<String, String>> B_X_AXIS_DESC_MAP = new EnumMap<OceanParamBinaryParser.VisualizeType, Map<String, String>>(OceanParamBinaryParser.VisualizeType.class) {{
        // 波高谱X轴
        put(OceanParamBinaryParser.VisualizeType.WAVE_HEIGHT_SPECTRUM, new HashMap<String, String>() {{
            put("name", "频率");
            put("unit", "Hz");
        }});
        // 波向谱X轴
        put(OceanParamBinaryParser.VisualizeType.WAVE_DIRECTION_SPECTRUM, new HashMap<String, String>() {{
            put("name", "频率");
            put("unit", "Hz");
        }});
    }};

    // 3. Y轴描述（key：可视化类型，value：包含中文名和单位的Map）
    private static final Map<OceanParamBinaryParser.VisualizeType, Map<String, String>> B_Y_AXIS_DESC_MAP = new EnumMap<OceanParamBinaryParser.VisualizeType, Map<String, String>>(OceanParamBinaryParser.VisualizeType.class) {{
        // 波高谱Y轴
        put(OceanParamBinaryParser.VisualizeType.WAVE_HEIGHT_SPECTRUM, new HashMap<String, String>() {{
            put("name", "波高谱密度");
            put("unit", "m²/Hz");
        }});
        // 波向谱Y轴
        put(OceanParamBinaryParser.VisualizeType.WAVE_DIRECTION_SPECTRUM, new HashMap<String, String>() {{
            put("name", "波向谱密度");
            put("unit", "°/Hz");
        }});
    }};

    /**
     * 按类型解析海面数据
     * @param requestBody 请求参数：
     *                    - filePath: 文件路径（必填）
     *                    - type: 可视化类型（必填，BASIC_PARAMS/WAVE_HEIGHT_SPECTRUM/WAVE_DIRECTION_SPECTRUM）
     * @return 解析结果（数据+单位描述）
     */
    @Anonymous
    @ApiOperation(value = "读取海洋基本特性数据", notes = "读取海洋基本特性数据")
    @PostMapping("/readOceanBasicParams")
    public AjaxResult readOceanBasicParams(@RequestBody Map<String, Object> requestBody) {
        // 1. 参数校验
        String filePath = (String) requestBody.get("filePath");
        String typeStr = (String) requestBody.get("type");
        if (filePath == null || filePath.isEmpty()) {
            return AjaxResult.error("filePath不能为空");
        }
        if (typeStr == null || typeStr.isEmpty()) {
            return AjaxResult.error("type不能为空");
        }

        // 2. 转换可视化类型
        OceanParamBinaryParser.VisualizeType type;
        try {
            type = OceanParamBinaryParser.VisualizeType.valueOf(typeStr.toUpperCase());
        } catch (IllegalArgumentException e) {
            return AjaxResult.error("无效的type参数，可选值: " + Arrays.toString(OceanParamBinaryParser.VisualizeType.values()));
        }

        // 3. 解析数据
        OceanParamBinaryParser parser = new OceanParamBinaryParser(filePath);
        if (!parser.readFile()) {
            return AjaxResult.error("文件读取失败");
        }
        try {
            parser.parse(type, false); // 解析指定类型
        } catch (Exception e) {
            return AjaxResult.error("解析失败: " + e.getMessage());
        }

        // 4. 构建返回结果（数据+单位描述）
        Map<String, Object> result = new HashMap<>();
        switch (type) {
            case BASIC_PARAMS:
                // 基本特性：返回参数值+参数描述（含单位）
                result.put("params", parser.getBasicParamsDTO());
                result.put("paramDescriptions", BASIC_PARAMS_DESC);
                break;
            case WAVE_HEIGHT_SPECTRUM:
            case WAVE_DIRECTION_SPECTRUM:
                // 谱数据：返回轴数据+轴描述（含单位）
                Map<String, List<Double>> spectrumData = parser.getSpectrumDTO(type);
                result.put("xAxis", spectrumData.get("xAxis"));
                result.put("yAxis", spectrumData.get("yAxis"));
                result.put("xAxisDesc", B_X_AXIS_DESC_MAP.get(type)); // X轴单位描述
                result.put("yAxisDesc", B_Y_AXIS_DESC_MAP.get(type)); // Y轴单位描述
                break;
        }

        return AjaxResult.success(result);
    }

    @Anonymous
    @ApiOperation(value = "读取ASC", notes = "读取ASC")
    @PostMapping("/readASC")
    public AjaxResult readAscFile(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }

        try {
            ModisDataParser parser = new ModisDataParser();
            Map<String, Object> result = parser.parseAndProcess(filePath);
            return success(result);
        } catch (IOException e) {
            return error("读取文件失败: " + e.getMessage());
        } catch (Exception e) {
            return error("处理文件失败: " + e.getMessage());
        }
    }

    @Anonymous
    @ApiOperation(value = "一二维参数列表", notes = "一二维参数列表")
    @PostMapping("/get2DParameters")
    public AjaxResult get2DParameters(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        return success(atmosphericNcFileService.get2DParameters(filePath)) ;
    }

    @Anonymous
    @ApiOperation(value = "读取二维", notes = "读取二维")
    @PostMapping("/read2DHeatmap")
    public AjaxResult read2DHeatmap(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        String val = request.get("val");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        return success(atmosphericNcFileService.read2DHeatmap(filePath,val)) ;
    }

    @Anonymous
    @ApiOperation(value = "读取二维生成热力图", notes = "读取二维生成热力图")
    @PostMapping("/read2DGenerateHeatmapImage")
    public AjaxResult read2DGenerateHeatmapImage(@RequestBody Map<String, String> request) throws IOException {
        String filePath = request.get("filePath");
        String val = request.get("val");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        BufferedImage image = atmosphericNcFileService.generateHeatmapImage(filePath,val);
         String base64 = imageToBase64(image);
        return success(base64);
    }

    // ---------------------- 辅助方法：BufferedImage 转 Base64（给前端用） ----------------------
    public String imageToBase64(BufferedImage image) throws IOException {
        java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
        javax.imageio.ImageIO.write(image, "png", baos);
        byte[] bytes = baos.toByteArray();
        return java.util.Base64.getEncoder().encodeToString(bytes);
    }
    @Anonymous
    @ApiOperation(value = "读取一维", notes = "读取一维")
    @PostMapping("/read1DLineChart")
    public AjaxResult read1DLineChart(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        String val = request.get("val");
        return success(atmosphericNcFileService.read1DLineChart(filePath,val));
    }

    @Anonymous
    @ApiOperation(value = "读取log文件（返回全部数据）-水平能见度", notes = "返回所有记录的时间和能见度数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filePath", value = "日志文件绝对路径", required = true, dataType = "String", paramType = "body")
    })
    @PostMapping("/readLogFile")
    public AjaxResult readLogFile(@RequestBody Map<String, Object> request) {
        // 1. 校验必传参数
        String filePath = (String) request.get("filePath");
        if (filePath == null || filePath.trim().isEmpty()) {
            return error("文件路径不能为空");
        }

        // 2. 获取处理结果并返回
        Map<String, Object> serviceResult = atmosphericNcFileService.readLogFile(filePath);
        return success(serviceResult);
    }




    @Anonymous
    @ApiOperation(value = "读取dat文件-获取海水流速流向时间", notes = "读取dat文件-获取海水流速流向时间")
    @PostMapping("/readDatBySeaCurrentTime")
    public AjaxResult readDatBySeaCurrentTime(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        return success(atmosphericNcFileService.readDatBySeaCurrentTime(filePath));
    }

    /**
     * 获取海水流速流向时序数据（适配前端折线图）
     * @param request 入参：filePath（.dat文件绝对路径）
     * @return 结构化结果：元信息 + 时序数据列表
     */
    @Anonymous
    @ApiOperation(value = "读取dat文件-获取海水流速流向时序数据", notes = "读取dat文件-获取海水流速流向时序数据")
    @PostMapping("/readDatBySeaCurrentTimeSeries")
    public AjaxResult readDatBySeaCurrentTimeSeries(@RequestBody Map<String, String> request) {
        // 1. 校验文件路径
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return AjaxResult.error("文件路径不能为空");
        }
        String targetTime = request.get("targetTime");

        // 3. 返回结果（前端直接解析data字段即可）
        return success(atmosphericNcFileService.readDatBySeaCurrentTimeSeries(filePath, targetTime));
    }

    @Anonymous
    @ApiOperation(value = "读取txt文件-获取海水流速流向时间", notes = "读取txt文件-获取海水流速流向时间")
    @PostMapping("/readTxtBySeaCurrentTime")
    public AjaxResult readTxtBySeaCurrentTime(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        return success(atmosphericNcFileService.readTxtBySeaCurrentTime(filePath));
    }
    @Anonymous
    @ApiOperation(value = "读取txt文件-获取海水流速流向时序数据", notes = "读取txt文件-获取海水流速流向时序数据")
    @PostMapping("/readTxtBySeaCurrentTimeSeries")
    public AjaxResult readTxtBySeaCurrentTimeSeries(@RequestBody Map<String, String> request) {
        // 1. 校验文件路径
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return AjaxResult.error("文件路径不能为空");
        }
        String targetTime = request.get("targetTime");

        // 3. 返回结果（前端直接解析data字段即可）
        return success(atmosphericNcFileService.readTxtBySeaCurrentTimeSeries(filePath, targetTime));
    }

    @Anonymous
    @ApiOperation(value = "读取OSF文件-获取全球温度盐度剖面时间", notes = "读取OSF文件-获取全球温度盐度剖面时间")
    @PostMapping("/readOsfUniversalTime")
    public AjaxResult readOsfUniversalTime(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        return success(atmosphericNcFileService.readOsfUniversalTime(filePath));
    }
    @Anonymous
    @ApiOperation(value = "读取OSF文件-获取全球温度盐度剖面数据", notes = "读取OSF文件-获取全球温度盐度剖面数据")
    @PostMapping("/readOsfUniversalProfile")
    public AjaxResult readOsfUniversalProfile(@RequestBody Map<String, String> request) {
        String filePath = request.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        String targetTime = request.get("targetTime");
        return success(atmosphericNcFileService.readOsfUniversalProfile(filePath, targetTime));
    }



    @Anonymous
    @ApiOperation(value = "读取mat文件-获取时间", notes = "读取mat文件-获取时间")
    @PostMapping("/processReadDateVariableByMat")
    private AjaxResult readDateVariableByMat(@RequestBody Map<String, Object> requestBody) throws IOException {
        // 校验filePath非空（必填参数）
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();

        // 处理year参数（可为空，不强制校验）
        Integer year = null;
        Object yearObj = requestBody.get("year");
        if (yearObj != null) {
            try {
                year = Integer.parseInt(yearObj.toString());
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("year参数格式错误，必须为整数", e);
            }
        }

        // 处理month参数（可为空，不强制校验）
        Integer month = null;
        Object monthObj = requestBody.get("month");
        if (monthObj != null) {
            try {
                month = Integer.parseInt(monthObj.toString());
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("month参数格式错误，必须为整数", e);
            }
        }

        // 调用服务层方法，传入可能为null的year和month
        return success(atmosphericNcFileService.readDateVariableByMat(filePath, year, month));
    }


    @Anonymous
    @ApiOperation(value = "读取Mat文件-读取水深深度层级", notes = "读取Mat文件-读取水深深度层级")
    @PostMapping("/processReadAllDepthLevel")
    public AjaxResult processReadAllDepthLevel(@RequestBody Map<String, Object> requestBody) throws IOException {
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();
        return success(atmosphericNcFileService.processReadAllDepthLevel(filePath));
    }



    @Anonymous
    @ApiOperation(value = "读取Mat文件-获取水深热力图", notes = "读取Mat文件-获取水深热力图")
    @PostMapping("/matFileReadOceanCurrentHeatmap")
    public AjaxResult matFileReadOceanCurrentHeatmap(@RequestBody Map<String, String> requestBody) throws IOException, InvalidRangeException {
        String filePath = requestBody.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }

        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        int depthIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("depthIndex"), "depthIndex不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        return success(atmosphericNcFileService.netcdfReadOceanCurrentHeatmap(filePath, timeIndex, depthIndex, val));
    }

    @Anonymous
    @ApiOperation(value = "读取Mat文件-获取水深时序图", notes = "读取Mat文件-获取水深时序图")
    @PostMapping("/matFileReadOceanCurrentLineChart")
    public AjaxResult matFileReadOceanCurrentLineChart(@RequestBody Map<String, String> requestBody) throws IOException {
        String filePath = requestBody.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }

        double targetLon = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLon"), "targetLon不能为空").toString());
        double targetLat = Double.parseDouble(Objects.requireNonNull(requestBody.get("targetLat"), "targetLat不能为空").toString());
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        int timeIndex = Integer.parseInt(Objects.requireNonNull(requestBody.get("timeIndex"), "timeIndex不能为空").toString());
        return success(atmosphericNcFileService.oceanCurrentDepthLineChart(filePath, targetLon, targetLat, val, timeIndex));
    }

    @Anonymous
    @ApiOperation(value = "特殊处理水深-读取水深NC的参数", notes = "特殊处理水深-读取水深NC的参数")
    @PostMapping("/processReadAllParametersByOceanCurrent")
    public AjaxResult processReadAllParametersByOceanCurrent(@RequestBody Map<String, Object> requestBody) throws IOException {
        String filePath = Objects.requireNonNull(
                requestBody.get("filePath"),
                "filePath参数不能为空"
        ).toString();
        return success(atmosphericNcFileService.processReadAllParametersByOceanCurrent(filePath));
    }
    @Anonymous
    @ApiOperation(value = "特殊处理水深-读取水深数据", notes = "特殊处理水深-读取水深数据")
    @PostMapping("/processReadOceanCurrentTimeSeries")
    public AjaxResult processReadOceanCurrentTimeSeries(@RequestBody Map<String, String> requestBody) throws IOException {
        String filePath = requestBody.get("filePath");
        if (filePath == null || filePath.isEmpty()) {
            return error("文件路径不能为空");
        }
        String val = Objects.requireNonNull(requestBody.get("val"), "val不能为空").toString();
        return success(atmosphericNcFileService.readOceanCurrentTimeSeries(filePath, val));
    }
}    